﻿using System.Linq;
using System.Collections.Generic;
using System.Configuration;
using System.Web;
using System.IO;

namespace CommerceOne.Common.Configs
{
    /// <summary>
    /// This was rewrited for testable purpose
    /// This class use HttpContextBase and IConfiguration 
    /// Tien 04-Aug: Refactor.
    /// </summary>
    public class WidgetConfiguration : ConfigurationSection
    {
        private HttpContextBase context;
        public HttpContextBase Context
        {
            set { context = value; }
        }

        #region Public constansts
        public const string SectionName = "widgetConfiguration";
        #endregion

        #region Configuration properties
        [ConfigurationProperty("baseFolder", DefaultValue = "~/Configs", IsRequired = false)]
        public string BaseFolder
        {
            get { return this["baseFolder"] as string; }
        }

        [ConfigurationProperty("widgetInstances")]
        public WidgetInstanceSettingsCollection WidgetInstances
        {
            get
            {
                return this["widgetInstances"] as WidgetInstanceSettingsCollection;
            }
            set
            {
                this["widgetInstances"] = value;
            }
        }
        #endregion

        /// <summary>
        /// Get all Widget configuration section
        /// Include all widget's instances settings infomation
        /// </summary>
        /// <returns></returns>
        public static WidgetConfiguration GetWidgetConfiguration(IConfigurationManager config)
        {
            return (WidgetConfiguration)config.GetSection<WidgetConfiguration>(WidgetConfiguration.SectionName);
        }

        /// <summary>
        /// Load all widget's instances into a dictionary
        /// </summary>
        /// <returns>IDictionary</returns>
        public IDictionary<string, WidgetInstanceSettings> GetWidgetInstanceDictionary()
        {
            int count = WidgetInstances.Count;

            if (count > 0)
            {
                Dictionary<string, WidgetInstanceSettings> instances = new Dictionary<string, WidgetInstanceSettings>(count);

                for (int i = 0; i < count; ++i)
                    instances.Add(WidgetInstances[i].Name, WidgetInstances[i]);

                return instances;
            }
            else
            {
                return null;
            }
        }

        /// <summary>
        /// Get name of xml config file of a widget instance by instance name
        /// </summary>
        /// <param name="instanceName">string</param>
        /// <returns>string</returns>
        public string GetConfigFileName(string instanceName)
        {
            Dictionary<string, WidgetInstanceSettings> instances = context.Application["WidgetInstances"] as Dictionary<string, WidgetInstanceSettings>;
            return ((WidgetInstanceSettings)instances[instanceName]).FileName;
        }

        /// <summary>
        /// Get fullpath of xml config file of a widget instance by instance name
        /// </summary>
        /// <param name="instanceName"></param>
        /// <returns></returns>
        public string GetConfigFilePath(string instanceName)
        {
            Dictionary<string, WidgetInstanceSettings> instances = (Dictionary<string, WidgetInstanceSettings>)context.Application["WidgetInstances"];
            string filePath = string.Format("{0}\\{1}", context.Server.MapPath(this.BaseFolder),
                ((WidgetInstanceSettings)instances[instanceName]).FileName);

            string result = GetConfigFile(new DirectoryInfo(context.Server.MapPath(this.BaseFolder)), ((WidgetInstanceSettings)instances[instanceName]).FileName);
            return result;
        }

        private string GetConfigFile(DirectoryInfo dictionaryInfo, string filename)
        {
            // First, process all the files directly under this folder
            string configPath = null;
            var fileInfo = dictionaryInfo.GetFiles("*.xml").FirstOrDefault(c => c.Name.ToLower() == filename.ToLower());
            if (fileInfo != null)
            {
                configPath =fileInfo.FullName;
                return configPath;
            }
            else
            {
                // Now find all the subdirectories under this directory.
                DirectoryInfo[] subDirs = dictionaryInfo.GetDirectories();

                foreach (DirectoryInfo dirInfo in subDirs)
                {
                    // Resursive call for each subdirectory.
                    configPath = GetConfigFile(dirInfo, filename);
                    if (configPath != null)
                    {
                        return configPath;
                    }
                }

                return configPath;
            }
        }
    }
}